package com.meiyuetao.myt.md.web.action;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import lab.s2jh.core.annotation.MetaData;
import lab.s2jh.core.exception.DataAccessDeniedException;
import lab.s2jh.core.pagination.GroupPropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter.MatchType;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.web.view.OperationResult;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.struts2.rest.HttpHeaders;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import com.meiyuetao.myt.core.web.MytBaseController;
import com.meiyuetao.myt.md.entity.CommodityPrice;
import com.meiyuetao.myt.md.entity.CommodityPrice.CommodityPriceRuleTypeEnum;
import com.meiyuetao.myt.md.service.CommodityPriceService;
import com.meiyuetao.myt.partner.entity.Partner;

@MetaData("CommodityPriceController")
public class CommodityPriceController extends MytBaseController<CommodityPrice, Long> {

    @Autowired
    private CommodityPriceService commodityPriceService;

    @Override
    protected BaseService<CommodityPrice, Long> getEntityService() {
        return commodityPriceService;
    }

    @Override
    protected void checkEntityAclPermission(CommodityPrice entity) {
        // 限定只能访问登录用户所在商家的数据
        Partner partner = getLogonPartner();
        if (partner != null && !partner.equals(entity.getCommodity().getPartner())) {
            throw new DataAccessDeniedException();
        }
    }

    @Override
    @MetaData("保存")
    public HttpHeaders doSave() {
        if (bindingEntity.getDefaultPrice()) {
            GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
            groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "commodity", bindingEntity.getCommodity()));
            List<CommodityPrice> commodityPrices = commodityPriceService.findByFilters(groupPropertyFilter);

            for (CommodityPrice item : commodityPrices) {
                if (item.getDefaultPrice()) {
                    item.setDefaultPrice(Boolean.FALSE);
                    commodityPriceService.save(item);
                }

            }
        }
        return super.doSave();
    }

    @Override
    @MetaData("删除")
    public HttpHeaders doDelete() {
        return super.doDelete();
    }

    @Override
    @MetaData("查询")
    public HttpHeaders findByPage() {
        return super.findByPage();
    }

    @Override
    protected String isDisallowDelete(CommodityPrice entity) {
        DateTime now = new DateTime();
        if (now.getMonthOfYear() == entity.getPriceMonth() && now.getYear() == entity.getPriceYear()) {
            return "当前月价格计划不能删除";
        }
        return null;
    }

    @MetaData("设置/取消默认")
    public HttpHeaders setOrCancelDefault() {
        String message = commodityPriceService.setOrCancelDefault(bindingEntity);
        setModel(OperationResult.buildSuccessResult(message));
        return buildDefaultHttpHeaders();
    }

    public HttpHeaders doRuleParamsRefresh() throws Exception {
        Long commoditySid = Long.valueOf(this.getParameter("commoditySid"));
        DateTime dateTime = new DateTime();
        HttpServletRequest request = this.getRequest();
        String startDateIn;
        String endDateIn;
        String ruleType = request.getParameter("ruleType");
        startDateIn = request.getParameter("startDate");
        endDateIn = request.getParameter("endDate");
        DateTime startDate = null;
        if (StringUtils.isNotBlank(startDateIn)) {
            startDate = new DateTime(startDateIn);
            startDate = new DateTime(startDate.getYear(), startDate.getMonthOfYear(), 1, 0, 0);
        } else {
            startDate = new DateTime(dateTime.getYear(), dateTime.getMonthOfYear(), 1, 0, 0);
        }
        DateTime endDate = null;
        if (StringUtils.isNotBlank(endDateIn)) {
            endDate = new DateTime(endDateIn);
            endDate = new DateTime(endDate.getYear(), endDate.getMonthOfYear(), 1, 0, 0);
        } else {
            endDate = startDate.plusMonths(11);
        }

        Period period = new Period(startDate, endDate, PeriodType.months());
        int months = period.getMonths();
        if (months <= 0) {
            months = 1;
            endDate = startDate.plusMonths(1);
        }
        GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
        groupPropertyFilter.append(new PropertyFilter(MatchType.GE, "priceTime", startDate.toDate()));
        groupPropertyFilter.append(new PropertyFilter(MatchType.LE, "priceTime", endDate.toDate()));
        groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "commodity.id", commoditySid));
        List<CommodityPrice> existsCommodityPrices = commodityPriceService.findByFilters(groupPropertyFilter);
        String coverPrice = this.getRequest().getParameter("coverPrice");
        if (CommodityPriceRuleTypeEnum.FREE_INPUT.name().equals(ruleType)) {
            for (int i = 0; i <= months; i++) {
                CommodityPrice commodityPrice = retrieveExistCommodityPrice(startDate.plusMonths(i).getYear(), startDate.plusMonths(i).getMonthOfYear(), existsCommodityPrices);
                if (StringUtils.isBlank(coverPrice) && commodityPrice != null) {
                    getCommodityPrices().add(commodityPrice);
                    continue;
                }
                commodityPrice = entityClass.newInstance();
                getCommodityPrices().add(commodityPrice);

                for (int idx = 0; idx <= 11; idx++) {
                    String price = request.getParameter("m" + idx + "Price");
                    if (StringUtils.isNotBlank(price)) {
                        Method setMethod = MethodUtils.getAccessibleMethod(CommodityPrice.class, "setM" + idx + "Price", new Class[] { BigDecimal.class });
                        setMethod.invoke(commodityPrice, new BigDecimal(price));
                    }
                }
                commodityPrice.setPriceYear(startDate.plusMonths(i).getYear());
                commodityPrice.setPriceMonth(startDate.plusMonths(i).getMonthOfYear());
            }
        } else if (CommodityPriceRuleTypeEnum.DECREASE_BY_MONTH_RATE.name().equals(ruleType)) {
            BigDecimal basePrice = new BigDecimal(this.getParameter("basePrice"));
            BigDecimal lowestPrice = new BigDecimal(this.getParameter("lowestPrice"));
            BigDecimal decreaseRate = new BigDecimal(this.getParameter("decreaseRate"));
            Integer decreaseMonths = new Integer(this.getParameter("decreaseMonths"));
            for (int i = 0; i <= months; i++) {
                CommodityPrice commodityPrice = retrieveExistCommodityPrice(startDate.plusMonths(i).getYear(), startDate.plusMonths(i).getMonthOfYear(), existsCommodityPrices);
                if (StringUtils.isBlank(coverPrice) && commodityPrice != null) {
                    getCommodityPrices().add(commodityPrice);
                    continue;
                }
                commodityPrice = new CommodityPrice();
                getCommodityPrices().add(commodityPrice);
                commodityPrice.setPriceYear(startDate.plusMonths(i).getYear());
                commodityPrice.setPriceMonth(startDate.plusMonths(i).getMonthOfYear());
                for (int j = 0; j <= decreaseMonths; j++) {
                    if (j == 0) {
                        commodityPrice.setM0Price(basePrice);
                    } else if (j <= 11) {
                        setupPrice(commodityPrice, decreaseRate, lowestPrice, j);
                    }
                }
            }

        } else if (CommodityPriceRuleTypeEnum.DECREASE_BY_GRADE.name().equals(ruleType)) {
            BigDecimal basePrice = new BigDecimal(this.getParameter("basePrice"));
            BigDecimal lowestPrice = new BigDecimal(this.getParameter("lowestPrice"));
            Integer decreaseMonths = new Integer(this.getParameter("decreaseMonths"));
            List<CommodityPrice> commodityPrices = commodityPriceService.calcCommodityPricesByGrade(startDate, endDate, basePrice, lowestPrice, decreaseMonths);

            if (StringUtils.isNotBlank(coverPrice) && coverPrice.equals("true")) {
                getCommodityPrices().addAll(commodityPrices);
            } else {
                getCommodityPrices().addAll(existsCommodityPrices);
                for (CommodityPrice commodityPrice : commodityPrices) {
                    Boolean isExists = false;
                    for (CommodityPrice existsCommodityPrice : existsCommodityPrices) {
                        if (commodityPrice.getPriceYear().equals(existsCommodityPrice.getPriceYear())
                                && commodityPrice.getPriceMonth().equals(existsCommodityPrice.getPriceMonth())) {
                            isExists = true;
                            break;
                        }
                    }
                    if (!isExists) {
                        getCommodityPrices().add(commodityPrice);
                    }
                }
            }
        }
        this.getRequest().setAttribute("commoditySid", commoditySid);
        return buildDefaultHttpHeaders("input-line");

    }

    private CommodityPrice retrieveExistCommodityPrice(Integer year, Integer month, List<CommodityPrice> existsCommodityPrices) {
        for (CommodityPrice commodityPrice : existsCommodityPrices) {
            if (commodityPrice.getPriceYear().equals(year) && commodityPrice.getPriceMonth().equals(month)) {
                return commodityPrice;
            }
        }
        return null;
    }

    private List<CommodityPrice> commodityPrices = new ArrayList<CommodityPrice>();

    public List<CommodityPrice> getCommodityPrices() {
        return commodityPrices;
    }

    public void setCommodityPrices(List<CommodityPrice> commodityPrices) {
        this.commodityPrices = commodityPrices;
    }

    private void setupPrice(CommodityPrice commodityPrice, BigDecimal decreaseRate, BigDecimal lowestPrice, int idx) throws Exception {
        Assert.isTrue(idx > 0 && idx <= 11);
        Method getMethod = MethodUtils.getAccessibleMethod(commodityPrice.getClass(), "getM" + (idx - 1) + "Price", new Class[] {});
        Method setMethod = MethodUtils.getAccessibleMethod(commodityPrice.getClass(), "setM" + idx + "Price", new Class[] { BigDecimal.class });
        BigDecimal prePrice = (BigDecimal) getMethod.invoke(commodityPrice);
        BigDecimal price;
        price = prePrice.multiply(decreaseRate).setScale(1, BigDecimal.ROUND_HALF_EVEN);
        if (lowestPrice != null) {
            if (price.compareTo(lowestPrice) < 0) {
                setMethod.invoke(commodityPrice, lowestPrice);
            } else {
                setMethod.invoke(commodityPrice, price);
            }

        } else {
            setMethod.invoke(commodityPrice, price);
        }
    }

    public HttpHeaders doBatchLine() throws Exception {
        String defaultPriceStrategy = this.getRequest().getParameter("defaultPriceStrategy");
        String ruleType = this.getRequest().getParameter("ruleType");
        Long commoditySid = Long.valueOf(this.getParameter("commoditySid"));
        commodityPriceService.doBatchLine(defaultPriceStrategy, ruleType, commoditySid, getCommodityPrices());
        setModel(OperationResult.buildSuccessResult("批量价格计划创建操作成功"));
        return buildDefaultHttpHeaders();

    }

}